package com.core.db.execute;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

import com.core.db.Connector;
import com.core.db.require.Require;

/**
 * sql操作执行器
 * 
 * @author 殷田
 *
 */
class Executor implements SqlAction
{
	private boolean autoCommit = false;
	private Connection conn;

	public Executor()
	{

	}

	public Executor( boolean autoCommit )
	{
		this.autoCommit = autoCommit;
	}

	public void setAutoCommit( boolean autoCommit )
	{
		this.autoCommit = autoCommit;
	}

	public Connection getConnection() throws SQLException
	{
		if ( !autoCommit )
		{
			if ( conn == null )
			{
				conn = Connector.get().getConnection();
				conn.setAutoCommit( false );
			}
			return conn;
		}
		Connection conn = Connector.get().getConnection();
		conn.setAutoCommit( true );
		return conn;
	}

	/**
	 * 查询操作
	 * 
	 * @param table
	 * @param cond
	 * @return
	 * @throws SQLException
	 */
	@Override
	public Result query( Require require ) throws SQLException
	{
		Connection conn = null;
		PreparedStatement stmt = null;
		try
		{
			String sql = require.sql();
			System.out.println( "query sql: "+sql );
			conn = getConnection();
			stmt = conn.prepareStatement( sql );
			prepareValuse( stmt, 1, require.getCondition().where().values() );
			return new Result( stmt, stmt.executeQuery() );
		}
		finally
		{
			release( conn, null );
		}
	}

	/**
	 * 插入操作
	 * 
	 * @param table
	 * @param cond
	 * @return
	 * @throws SQLException
	 */
	@Override
	public boolean insert( Require require ) throws SQLException
	{
		Connection conn = null;
		PreparedStatement stmt = null;
		try
		{
			String sql = require.sql();
			System.out.println( "insert sql: "+sql );
			conn = getConnection();
			stmt = conn.prepareStatement( sql );
			prepareValuse( stmt, 1, require.getValues() );
			return stmt.execute();
		}
		finally
		{
			release( conn, stmt );
		}
	}

	/**
	 * 删除操作
	 * 
	 * @param table
	 * @param cond
	 * @return
	 * @throws SQLException
	 */
	@Override
	public boolean delect( Require require ) throws SQLException
	{
		Connection conn = null;
		PreparedStatement stmt = null;
		try
		{
			String sql = require.sql();
			System.out.println( "delect sql: "+sql );
			conn = getConnection();
			stmt = conn.prepareStatement( sql );
			prepareValuse( stmt, 1, require.getCondition().where().values() );
			return stmt.execute();
		}
		finally
		{
			release( conn, stmt );
		}
	}

	/**
	 * 更新操作
	 * 
	 * @param table
	 * @param cond
	 * @return
	 * @throws SQLException
	 */
	@Override
	public boolean update( Require require ) throws SQLException
	{
		Connection conn = null;
		PreparedStatement stmt = null;
		try
		{
			String sql = require.sql();
			System.out.println( "update sql: "+sql );
			conn = getConnection();
			stmt = conn.prepareStatement( sql );
			List< Object > columnValues = require.getValues();
			prepareValuse( stmt, 1, columnValues );
			prepareValuse( stmt, columnValues.size() + 1, require.getCondition().where().values() );
			return stmt.execute();
		}
		finally
		{
			release( conn, stmt );
		}
	}

	/**
	 * 直接执行查询sql
	 * 
	 * @param sql
	 * @return
	 * @throws SQLException
	 */
	@Override
	public Result rawQuery( String sql ) throws SQLException
	{
		Connection conn = null;
		PreparedStatement stmt = null;
		try
		{
			conn = getConnection();
			stmt = conn.prepareStatement( sql );
			return new Result( stmt, stmt.executeQuery( sql ) );
		}
		finally
		{
			release( conn, null );
		}
	}

	/**
	 * 直接执行sql语句
	 * 
	 * @param sql
	 * @return
	 * @throws SQLException
	 */
	@Override
	public boolean raw( String sql ) throws SQLException
	{
		Connection conn = null;
		PreparedStatement stmt = null;
		try
		{
			conn = getConnection();
			stmt = conn.prepareStatement( sql );
			return stmt.execute( sql );
		}
		finally
		{
			release( conn, stmt );
		}
	}

	/**
	 * 填充values
	 * 
	 * @param stmt
	 * @param paramStartIndex
	 * @param values
	 * @throws SQLException
	 */
	private void prepareValuse( PreparedStatement stmt, int paramStartIndex, List< Object > values )
					throws SQLException
	{
		if ( values != null && values.size() > 0 )
		{
			for ( int i = 0; i < values.size(); i++ )
			{
				stmt.setObject( paramStartIndex + i, values.get( i ) );
			}
		}
	}

	/**
	 * 用于关闭资源的块
	 * 
	 * @param conn
	 * @param stmt
	 */
	private void release( Connection conn, PreparedStatement stmt )
	{
		try
		{
			if ( stmt != null )
			{
				stmt.close();
			}
		}
		catch ( SQLException se2 )
		{
		}
		try
		{
			if ( conn != null )
			{
				conn.close();
			}
		}
		catch ( SQLException se )
		{
		}
	}
}
